const createRedisClient = require('../config/redis');

class RedisService {
  constructor() {
    this.client = null;
    this.isConnected = false;
  }

  // 初始化Redis连接
  async init() {
    try {
      this.client = await createRedisClient();
      if (this.client) {
        this.isConnected = true;
        return this.client;
      } else {
        this.isConnected = false;
        console.log('Redis服务不可用，应用将在无Redis模式下运行');
        return null;
      }
    } catch (error) {
      console.warn('Redis服务初始化失败:', error.message);
      this.isConnected = false;
      return null;
    }
  }

  // 检查连接状态
  isReady() {
    return this.isConnected && this.client && this.client.isReady;
  }

  // 设置键值对
  async set(key, value, expireTime = null) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const stringValue = typeof value === 'object' ? JSON.stringify(value) : String(value);
      
      if (expireTime) {
        await this.client.setEx(key, expireTime, stringValue);
      } else {
        await this.client.set(key, stringValue);
      }
      
      return true;
    } catch (error) {
      console.error('Redis SET操作失败:', error);
      throw error;
    }
  }

  // 获取值
  async get(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const value = await this.client.get(key);
      if (value === null) {
        return null;
      }

      // 尝试解析JSON，如果失败则返回原始字符串
      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      console.error('Redis GET操作失败:', error);
      throw error;
    }
  }

  // 删除键
  async del(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const result = await this.client.del(key);
      return result > 0;
    } catch (error) {
      console.error('Redis DEL操作失败:', error);
      throw error;
    }
  }

  // 检查键是否存在
  async exists(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const result = await this.client.exists(key);
      return result === 1;
    } catch (error) {
      console.error('Redis EXISTS操作失败:', error);
      throw error;
    }
  }

  // 设置过期时间
  async expire(key, seconds) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const result = await this.client.expire(key, seconds);
      return result === 1;
    } catch (error) {
      console.error('Redis EXPIRE操作失败:', error);
      throw error;
    }
  }

  // 获取剩余过期时间
  async ttl(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      return await this.client.ttl(key);
    } catch (error) {
      console.error('Redis TTL操作失败:', error);
      throw error;
    }
  }

  // 哈希操作 - 设置哈希字段
  async hSet(key, field, value) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const stringValue = typeof value === 'object' ? JSON.stringify(value) : String(value);
      await this.client.hSet(key, field, stringValue);
      return true;
    } catch (error) {
      console.error('Redis HSET操作失败:', error);
      throw error;
    }
  }

  // 哈希操作 - 获取哈希字段
  async hGet(key, field) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const value = await this.client.hGet(key, field);
      if (value === null) {
        return null;
      }

      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      console.error('Redis HGET操作失败:', error);
      throw error;
    }
  }

  // 哈希操作 - 获取所有哈希字段
  async hGetAll(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const hash = await this.client.hGetAll(key);
      const result = {};
      
      for (const [field, value] of Object.entries(hash)) {
        try {
          result[field] = JSON.parse(value);
        } catch {
          result[field] = value;
        }
      }
      
      return result;
    } catch (error) {
      console.error('Redis HGETALL操作失败:', error);
      throw error;
    }
  }

  // 列表操作 - 左推入
  async lPush(key, ...values) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const stringValues = values.map(v => 
        typeof v === 'object' ? JSON.stringify(v) : String(v)
      );
      return await this.client.lPush(key, stringValues);
    } catch (error) {
      console.error('Redis LPUSH操作失败:', error);
      throw error;
    }
  }

  // 列表操作 - 右弹出
  async rPop(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const value = await this.client.rPop(key);
      if (value === null) {
        return null;
      }

      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      console.error('Redis RPOP操作失败:', error);
      throw error;
    }
  }

  // 获取列表长度
  async lLen(key) {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      return await this.client.lLen(key);
    } catch (error) {
      console.error('Redis LLEN操作失败:', error);
      throw error;
    }
  }

  // 关闭连接
  async close() {
    if (this.client) {
      try {
        await this.client.quit();
        this.isConnected = false;
        console.log('Redis连接已关闭');
      } catch (error) {
        console.error('关闭Redis连接失败:', error);
      }
    }
  }

  // 测试连接
  async ping() {
    if (!this.isReady()) {
      throw new Error('Redis连接未就绪');
    }

    try {
      const result = await this.client.ping();
      return result === 'PONG';
    } catch (error) {
      console.error('Redis PING失败:', error);
      throw error;
    }
  }
}

// 创建单例实例
const redisService = new RedisService();

module.exports = redisService;